<?php
class Tag_Manager extends Model {
	
	private $_current_blogger_id;
	
	function Tag_Manager() {
		parent::Model();
		$this->_current_blogger_id = 0;
	}
	
	function SetCurrentBloggerID($current_blogger_id) {
		$this->_current_blogger_id = $current_blogger_id;
	}
	
	function AddTags($str_tags, $entry_id) {
		if(strlen($str_tags) == 0) {
			return;
		}
		
		$arr_tags = explode(' ', trim($str_tags));
		foreach($arr_tags as $tag) {
			$this->doAddTag($tag, $entry_id);
		}
	}
	
	private function doAddTag($tag_text, $entry_id) {
		$parms = array(
			'tag_text' => $tag_text,
			'entry_id' => $entry_id,
			'blogger_id' => $this->_current_blogger_id
		);
		$this->db->insert('nt_tags', $parms);
	}
	
	function UpdateTags($str_tags, $entry_id) {
		// delete first, then add
		$this->db->query('DELETE FROM `nt_tags` WHERE `entry_id` = ?', array($entry_id));
		$this->AddTags($str_tags, $entry_id);
	}
	
	// Get tag-list of current user/all users (for front-page)
	function GetTagList($of_all = FALSE, $low = 0) {
		$sql = '';
		$qry = NULL;
		if(!$of_all) { // current user's tags
			$sql = 'SELECT COUNT(t.`entry_id`) AS entry_num, t.`tag_text`, 0 AS tag_level FROM `nt_tags` t WHERE t.`blogger_id` = ? AND t.`entry_id` IN (SELECT e.`id` FROM `nt_entries` e WHERE e.`blogger_id` = ? AND e.`state` = 1) GROUP BY `tag_text` ORDER BY `tag_text`';
			$qry = $this->db->query($sql, array($this->_current_blogger_id, $this->_current_blogger_id));
		} else {
			$sql = 'SELECT COUNT(t.`entry_id`) AS entry_num, t.`tag_text`, 0 AS tag_level FROM `nt_tags` t WHERE t.`entry_id` IN (SELECT e.`id` FROM `nt_entries` e WHERE e.`state` = 1) AND t.`blogger_id` IN (SELECT bi.`blogger_id` FROM `nt_blogger_info` bi WHERE bi.`show` = 1) GROUP BY t.`tag_text` HAVING COUNT(t.`entry_id`) > ? ORDER BY t.`tag_text`'; // $low indicates minimal tag occurrence
			$qry = $this->db->query($sql, array($low));
		}
		return $qry->result();
	}
	
	function maxTagNum($tag_items) {
		if(count($tag_items) <= 0) {
			return 0;
		}
		$max = $tag_items[0]->entry_num;
		foreach($tag_items as $tag_item) {
			if($tag_item->entry_num > $max) {
				$max = $tag_item->entry_num;
			}
		}
		return $max;
	}
	
	function minTagNum($tag_items) {
		if(count($tag_items) <= 0) {
			return 0;
		}
		$min = $tag_items[0]->entry_num;
		foreach($tag_items as $tag_item) {
			if($tag_item->entry_num < $min) {
				$min = $tag_item->entry_num;
			}
		}
		return $min;
	}
	
	function CalcTagLevel($tag_items) {
		if(count($tag_items) <= 0) {
			return $tag_items;
		}
		
		$min_level = 1;
		
		$max = $this->maxTagNum($tag_items);
		$min = $this->minTagNum($tag_items);
		
		$d = round($max / $min);
		$max_level = ($d > 10) ? 10 : $d;
		
		$lv = 1;
		foreach($tag_items as $tag_item) {
			if($max > $min) {
				$lv = (log10($tag_item->entry_num) - log10($min)) / (log10($max) - log10($min)) * ($max_level - $min_level) + $min_level;
				if($lv > $max_level) {
					$lv = $lv / $max_level;
				}
			} else {
				$lv = 1;
			}
			$tag_item->tag_level = round($lv);
		}
		return $tag_items;
	}
	
	function GetEntryListByTag($tag_query, $of_all = FALSE) {
		$sql = $this->buildSQL($tag_query, $of_all);
		$qry = NULL;
		if(!$of_all) {
			$qry = $this->db->query($sql, array($this->_current_blogger_id));
		} else {
			$qry = $this->db->query($sql);
		}
		return $qry->result();
	}
	
	private function buildSQL($tag_query, $of_all) {
		$of_blogger = '';
		$tag_comma = '';
		$ret = '';
		if(!$of_all) {
			$of_blogger = ' AND t.`blogger_id` = ?';
		}
		if(strpos($tag_query, '|') > 0) { // or
			$ors = explode('|', $tag_query);
			for($i = 0; $i < count($ors); $i++) {
				$tag_comma .= $this->db->escape($ors[$i]);
				if($i < count($ors) - 1) {
					$tag_comma .= ', ';
				}
			}
			$ret = 'SELECT e.`id`, e.`post_time`, e.`title`, e.`expression`, LEFT(ed.`content`, 128) AS content_top, e.`state`, e.`blogger_id`, e.`tags`, e.`comment_num` FROM `nt_entry_data` ed JOIN `nt_entries` e ON ed.`entry_id` = e.`id` WHERE e.`id` IN (SELECT t.`entry_id` FROM `nt_tags` t WHERE t.`tag_text` IN (' . $tag_comma . ')' . $of_blogger . ' GROUP BY t.`entry_id`) AND e.`state` = 1 ORDER BY e.`post_time` DESC, e.`id` DESC';
		} elseif(strpos($tag_query, '+')) { // and
			$ands = explode('+', $tag_query);
			$tag_num = count($ands);
			for($j = 0; $j < count($ands); $j++) {
				$tag_comma .= $this->db->escape($ands[$j]);
				if($j < count($ands) - 1) {
					$tag_comma .= ', ';
				}
			}
			$ret = 'SELECT e.`id`, e.`post_time`, e.`title`, e.`expression`, LEFT(ed.`content`, 128) AS content_top, e.`state`, e.`blogger_id`, e.`tags`, e.`comment_num` FROM `nt_entry_data` ed JOIN `nt_entries` e ON ed.`entry_id` = e.`id` WHERE e.`id` IN (SELECT t.`entry_id` FROM `nt_tags` t WHERE t.`tag_text` IN (' . $tag_comma . ')' . $of_blogger . ' GROUP BY t.`entry_id` HAVING COUNT(t.`entry_id`) = ' . $tag_num . ') AND e.`state` = 1 ORDER BY e.`post_time` DESC, e.`id` DESC';
		} else { // single tag
			$tag_query = $this->db->escape($tag_query);
			$ret = 'SELECT e.`id`, e.`post_time`, e.`title`, e.`expression`, LEFT(ed.`content`, 128) AS content_top, e.`state`, e.`blogger_id`, e.`tags`, e.`comment_num` FROM `nt_entry_data` ed JOIN `nt_entries` e ON ed.`entry_id` = e.`id` WHERE e.`id` IN (SELECT t.`entry_id` FROM `nt_tags` t WHERE t.`tag_text` = ' . $tag_query . '' . $of_blogger . ' GROUP BY t.`entry_id`) AND e.`state` = 1 ORDER BY e.`post_time` DESC, e.`id` DESC';
		}
		return $ret;
	}
	
	function BatchRenameTag($old_tag, $new_tag_string) {
		$qry = $this->db->query('SELECT `entry_id` FROM `nt_tags` WHERE `blogger_id` = ? AND `tag_text` = ?', array($this->_current_blogger_id, $old_tag));
		if($qry->num_rows() > 0) {
			foreach($qry->result() as $eid) {
				$qry1 = $this->db->query('SELECT `tags` FROM `nt_entries` WHERE `id` = ? AND `blogger_id` = ?', array($eid->entry_id, $this->_current_blogger_id));
				$old_tags = $qry1->row()->tags;
				$new_tags = str_replace($old_tag, $new_tag_string, $old_tags);
				$this->db->query('UPDATE `nt_entries` SET `tags` = ? WHERE `id` = ? AND `blogger_id` = ?', array($new_tags, $eid->entry_id, $this->_current_blogger_id));
				$this->UpdateTags($new_tags, $eid->entry_id);
			}
		}
	}
	
	function DeleteTag($tag) {
		$qry = $this->db->query('SELECT `entry_id` FROM `nt_tags` WHERE `blogger_id` = ? AND `tag_text` = ?', array($this->_current_blogger_id, $tag));
		if($qry->num_rows() > 0) {
			foreach($qry->result() as $eid) {
				$qry1 = $this->db->query('SELECT `tags` FROM `nt_entries` WHERE `id` = ? AND `blogger_id` = ?', array($eid->entry_id, $this->_current_blogger_id));
				$old_tags = $qry1->row()->tags;
				$new_tags = str_replace($tag, '', $old_tags);
				$new_tags = preg_replace('/\s{2,}/', ' ', $new_tags);
				$this->db->query('UPDATE `nt_entries` SET `tags` = ? WHERE `id` = ? AND `blogger_id` = ?', array($new_tags, $eid->entry_id, $this->_current_blogger_id));
			}
		}
		$this->db->query('DELETE FROM `nt_tags` WHERE `blogger_id` = ? AND `tag_text` = ?', array($this->_current_blogger_id, $tag));
	}
}
?>